package com.uvstu.system.controller;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSONObject;
import com.uvstu.common.config.RuoYiConfig;
import com.uvstu.common.core.domain.entity.SysUser;
import com.uvstu.common.exception.TClientException;
import com.uvstu.common.pay.client.AliPayClient;
import com.uvstu.common.pay.client.WxPayClient;
import com.uvstu.common.upay.Result;
import com.uvstu.common.upay.pay.AliPayUtil;
import com.uvstu.common.upay.pay.WxPayUtil;
import com.uvstu.common.upay.pay.config.AliPayConfigUtil;
import com.uvstu.common.upay.pay.config.WxPayConfigUtil;
import com.uvstu.common.utils.HttpsUtil;
import com.uvstu.common.utils.SecurityUtils;
import com.uvstu.system.domain.SApplication;
import com.uvstu.system.domain.SOrder;
import com.uvstu.system.domain.SPayConfig;
import com.uvstu.system.service.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.uvstu.common.annotation.Log;
import com.uvstu.common.core.controller.BaseController;
import com.uvstu.common.core.domain.AjaxResult;
import com.uvstu.common.enums.BusinessType;
import com.uvstu.system.domain.SUorder;
import com.uvstu.common.utils.poi.ExcelUtil;
import com.uvstu.common.core.page.TableDataInfo;

/**
 * 用户订单Controller
 * 
 * @author zwb
 * @date 2023-02-07
 */
@RestController
@RequestMapping("/system/uorder")
public class SUorderController extends BaseController
{
    @Autowired
    private ISUorderService sUorderService;

    @Autowired
    private ISApplicationService isApplicationService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private ISPayConfigService isPayConfigService;

    @Autowired
    private ISysDictDataService dictDataService;

    /**
     * 查询用户订单列表
     */
    @GetMapping("/list")
    public TableDataInfo list(SUorder sUorder)
    {
        startPage();
        List<SUorder> list = sUorderService.selectSUorderList(sUorder);
        return getDataTable(list);
    }

    /**
     * 导出用户订单列表
     */
    @Log(title = "用户订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SUorder sUorder)
    {
        List<SUorder> list = sUorderService.selectSUorderList(sUorder);
        ExcelUtil<SUorder> util = new ExcelUtil<SUorder>(SUorder.class);
        util.exportExcel(response, list, "用户订单数据");
    }

    /**
     * 获取用户订单详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(sUorderService.selectSUorderById(id));
    }

    /**
     * 新增用户订单
     */
    @Log(title = "用户订单", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SUorder sUorder)
    {
        return toAjax(sUorderService.insertSUorder(sUorder));
    }

    /**
     * 修改用户订单
     */
    @Log(title = "用户订单", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SUorder sUorder)
    {
        return toAjax(sUorderService.updateSUorder(sUorder));
    }

    /**
     * 删除用户订单
     */
    @Log(title = "用户订单", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(sUorderService.deleteSUorderByIds(ids));
    }

    /**
     * 重发通知
     * @param sUorder
     * @return
     * @throws TClientException
     */
    @RequestMapping("orderNotice")
    public Result orderNotice(SUorder sUorder) throws TClientException {
        Result result = new Result();
        sUorder = sUorderService.selectSUorderById(sUorder.getId());
        if(sUorder == null){
            throw new TClientException("重发通知失败，订单不存在！");
        }
        //查询应用
        SApplication sApplication =  isApplicationService.selectSApplicationByAppid(sUorder.getAppId());
        if(sApplication == null){
            throw new TClientException("重发通知失败，应用不存在！");
        }
        try{
            JSONObject data = new JSONObject();
            data.put("appid",sUorder.getAppId());
            data.put("outTradeNo",sUorder.getOutTradeNo());
            data.put("tradeNo",sUorder.getTradeNo());
            data.put("refundNo",sUorder.getRefundNo());
            data.put("goodName",sUorder.getGoodName());
            data.put("payMethod",sUorder.getPayMethod());
            data.put("price",sUorder.getPrice());
            data.put("transactionTime",sUorder.getTransactionTime());
            data.put("status",sUorder.getStatus());
            data.put("refundTime",sUorder.getRefundTime());
            data.put("createTime",sUorder.getCreateTime());
            if(sUorder.getStatus() == 2){
                //支付成功
                HttpsUtil.doPost(sApplication.getNotifyUrl(),JSONObject.toJSONString(data));
            }else if(sUorder.getStatus() == 5){
                //退款成功
                HttpsUtil.doPost(sApplication.getRefundUrl(),JSONObject.toJSONString(data));
            }
        }catch (Exception e){
            throw new TClientException("重发通知失败，HTTP请求异常！");
        }
        result.setSccess("重复通知成功！");
        return result;
    }

    /**
     * 退款
     */
    @RequestMapping("refund")
    public Result refund(SUorder sUorder) throws TClientException {
        Result result = new Result();
        sUorder = sUorderService.selectSUorderById(sUorder.getId());
        if(sUorder == null){
            throw new TClientException("退款失败，订单不存在！");
        }
        if(!isNow(sUorder.getTransactionTime())){
            throw new TClientException("退款失败，只允许退款单天的订单");
        }
        //查询应用
        SApplication sApplication =  isApplicationService.selectSApplicationByAppid(sUorder.getAppId());
        if(sApplication == null){
            throw new TClientException("退款失败，应用不存在！");
        }
        //判断退款类型
        if(sUorder.getPayMethod() == 1){
            //支付宝
            SPayConfig sPayConfig = new SPayConfig();
            sPayConfig.setPayStatus("2");
            sPayConfig.setPaymentChannel("1");
            List<SPayConfig> sPayConfigList = isPayConfigService.selectSPayConfigList(sPayConfig);
            if(sPayConfigList.size() == 0){
                throw new TClientException("平台无可用的支付宝通道,请联系管理员！");
            }
            sPayConfig = sPayConfigList.get(0);
            String notifyUrl = configService.selectConfigByKey("sys.url") + "/open/pay/api/uAliPayNotify";
            //封装参数
            try{
                AliPayConfigUtil aliPayConfigUtil = new AliPayConfigUtil(sPayConfig.getGatewayAddress(),sPayConfig.getAppid(),
                        sPayConfig.getKey1(),sPayConfig.getKey2(),dictDataService.selectDictLabel("sign_type",
                        sPayConfig.getSignType()),sPayConfig.getDataFormat(),
                        dictDataService.selectDictLabel("coding_set", sPayConfig.getCodingSet()),notifyUrl,sApplication.getReturnUrl());
                BigDecimal price = new BigDecimal(0);
                if(sUorder.getPrice().compareTo(new BigDecimal(1)) != -1){
                    price = sUorder.getPrice().multiply(new BigDecimal(0.994)).setScale(2, RoundingMode.HALF_UP);
                }else{
                    price = sUorder.getPrice();
                }
                Map<String,Object> map = AliPayUtil.refund(aliPayConfigUtil,sUorder.getOutTradeNo(),sUorder.getTradeNo(),String.valueOf(price),"平台退款(已扣除平台交易手续费)");
                if(map.get("alipay_trade_refund_response") != null){
                    String json = JSONObject.parseObject(JSONObject.toJSONString(map.get("alipay_trade_refund_response"))).getString("msg");
                    if("Success".equals(json)){
                        sUorder.setRefundTime(new Date());
                        sUorder.setStatus(5);
                        sUorder.setPayParam(JSONObject.toJSONString(map));
                        sUorderService.updateSUorderResult(sUorder);
                        //通知第三方用户退款结果
                        JSONObject data = new JSONObject();
                        data.put("appid",sUorder.getAppId());
                        data.put("outTradeNo",sUorder.getOutTradeNo());
                        data.put("tradeNo",sUorder.getTradeNo());
                        data.put("refundNo",sUorder.getRefundNo());
                        data.put("goodName",sUorder.getGoodName());
                        data.put("payMethod",sUorder.getPayMethod());
                        data.put("price",sUorder.getPrice());
                        data.put("transactionTime",sUorder.getTransactionTime());
                        data.put("status",sUorder.getStatus());
                        data.put("refundTime",sUorder.getRefundTime());
                        data.put("createTime",sUorder.getCreateTime());
                        HttpsUtil.doPost(sApplication.getRefundUrl(),JSONObject.toJSONString(data));
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
                throw new TClientException("第三方请求参数错误！");
            }
        }else{
            //微信
            SPayConfig sPayConfig = new SPayConfig();
            sPayConfig.setPayStatus("2");
            sPayConfig.setPaymentChannel("2");
            List<SPayConfig> sPayConfigList = isPayConfigService.selectSPayConfigList(sPayConfig);
            if(sPayConfigList.size() == 0){
                throw new TClientException("平台无可用的微信通道,请联系管理员！");
            }
            sPayConfig = sPayConfigList.get(0);
            String payNotifyUrl = configService.selectConfigByKey("sys.url") + "/open/pay/api/uWxPayNotify";
            String refundNotifyUrl = configService.selectConfigByKey("sys.url") + "/open/pay/api/uWxRefundNotify";
            //封装参数
            try{
                String[] arr = sPayConfig.getCertificatePath().split(",");
                String certificatePath = "";
                for (int i = 0; i < arr.length; i++) {
                    if(arr[i].indexOf("p12") != -1){
                        certificatePath = RuoYiConfig.getProfile() + arr[i].replace("/profile/","/");
                    }
                }
                WxPayConfigUtil wxPayConfigUtil = new WxPayConfigUtil();
                wxPayConfigUtil.setConfig(sPayConfig.getAppid(),sPayConfig.getKey2(),sPayConfig.getKey1(),payNotifyUrl,refundNotifyUrl,
                        certificatePath,sPayConfig.getKey1());
                int price = (int)(Double.valueOf(sUorder.getPrice().toString())*100);
                Map<String,String> map = WxPayUtil.refund(wxPayConfigUtil,sUorder.getTradeNo(),sUorder.getOutTradeNo(),String.valueOf(price),String.valueOf(price),"平台全额退款");
                sUorder.setStatus(4);
                sUorder.setRefundNo(map.get("refund_id"));
                sUorderService.updateSUorderResult(sUorder);
            }catch (Exception e){
                e.printStackTrace();
                throw new TClientException("第三方请求参数错误！");
            }
        }
        return result;
    }


    /**
     * 订单同步
     */
    @RequestMapping("/orderSyn")
    public void orderSyn(){
        Thread thread = new Thread(new Runnable(){
            @Override
            public void run() {
                try{
                    //执行支付支付订单和退款订单
                    SUorder sUorder = new SUorder();
                    sUorder.setStatus(1);
                    List<SUorder> payOrder = sUorderService.selectOrderData(sUorder);
                    updataPayOrder(payOrder);
                    sUorder.setStatus(4);
                    List<SUorder> refundOrder = sUorderService.selectOrderData(sUorder);
                    updataRefundOrder(refundOrder);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }

    /**
     * 同步退款订单
     * @param refundOrder
     */
    private void updataRefundOrder(List<SUorder> refundOrder) {
        for (int i = 0; i < refundOrder.size(); i++) {
            switch (refundOrder.get(i).getPayMethod()){
                case 1:
                    try{
                        Map<String,Object> map = AliPayClient.refundQuery(refundOrder.get(i).getOutTradeNo(),refundOrder.get(i).getTradeNo());
                        if(map.get("alipay_trade_fastpay_refund_query_response") != null){
                            JSONObject result = JSONObject.parseObject(JSONObject.toJSONString(map.get("alipay_trade_fastpay_refund_query_response")));
                            if("REFUND_SUCCESS".equals(result.getString("refund_status"))){
                                //退款成功
                                refundOrder.get(i).setStatus(5);
                                sUorderService.updateSUorder(refundOrder.get(i));
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
                case 2:
                    try{
                        Map<String,String> result = WxPayClient.refundQuery(refundOrder.get(i).getRefundNo());
                        if("SUCCESS".equals(result.get("result_code"))){
                            //支付成功
                            refundOrder.get(i).setStatus(5);
                            sUorderService.updateSUorder(refundOrder.get(i));
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    /**
     * 同步支付订单
     * @param payOrder
     */
    private void updataPayOrder(List<SUorder> payOrder) {
        for (int i = 0; i < payOrder.size(); i++) {
            switch (payOrder.get(i).getPayMethod()){
                case 1:
                    try{
                        Map<String,Object> map = AliPayClient.payQuery(payOrder.get(i).getOutTradeNo(),payOrder.get(i).getTradeNo());
                        if(map.get("alipay_trade_query_response") != null){
                            JSONObject result = JSONObject.parseObject(JSONObject.toJSONString(map.get("alipay_trade_query_response")));
                            if("TRADE_SUCCESS".equals(result.getString("trade_status"))){
                                //支付成功
                                payOrder.get(i).setTradeNo(result.getString("trade_no"));
                                payOrder.get(i).setStatus(2);
                                sUorderService.updateSUorder(payOrder.get(i));
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
                case 2:
                    try{
                        Map<String,String> result = WxPayClient.payQuery(payOrder.get(i).getTradeNo());
                        if("SUCCESS".equals(result.get("trade_state"))){
                            //支付成功
                            payOrder.get(i).setStatus(2);
                            sUorderService.updateSUorder(payOrder.get(i));
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    /**
     * 判断日期是不是今天
     * @param date
     * @return    是返回true，不是返回false
     */
    public boolean isNow(Date date) {
        Date now = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        String nowDay = sf.format(now);
        String day = sf.format(date);
        return day.equals(nowDay);
    }


}
